#include "stdafx.h"
#include "gp.h"
#include "gp_Ax2d.h"
#include "gp_Pnt2d.h"
#include "gp_Dir2d.h"
#include "gp_Trsf2d.h"
#include "gp_Vec2d.h"
#include "gp_Lin2d.h"

//=======================================================================
//function : gp_Lin2d
//purpose  : 
//=======================================================================

gp_Lin2d::gp_Lin2d (const double A,
                    const double B,
                    const double C)
{
  const double Norm2 = A * A + B * B;
  Standard_ConstructionError_Raise_if (Norm2 <= gp::Resolution(), " ");
  const gp_Pnt2d P (-A*C/Norm2, -B*C/Norm2);
  const gp_Dir2d V (-B, A);

//   gp_Pnt2d P;
//   double Norm = sqrt(A * A + B * B);
//   Standard_ConstructionError_Raise_if (Norm <= gp::Resolution(), " ");
//   double A1 = A/Norm;
//   double B1 = B/Norm;
//   double C1 = C/Norm;
//   gp_Dir2d V = gp_Dir2d (-B1, A1);
//   double AA1 = A1;
//   if (AA1 < 0) AA1 = - AA1;
//   if (AA1 > gp::Resolution()) P.SetCoord (-C1 / A1, 0.0);
//   else                        P.SetCoord (0.0, -C1 / B1);

  pos = gp_Ax2d(P, V);
}

//=======================================================================
//function : Mirror
//purpose  : 
//=======================================================================

void gp_Lin2d::Mirror (const gp_Pnt2d& P)
{ pos.Mirror(P);  }

//=======================================================================
//function : Mirrored
//purpose  : 
//=======================================================================

gp_Lin2d gp_Lin2d::Mirrored (const gp_Pnt2d& P)  const
{
  gp_Lin2d L = *this;    
  L.pos.Mirror(P);
  return L;
}

//=======================================================================
//function : Mirror
//purpose  : 
//=======================================================================

void gp_Lin2d::Mirror (const gp_Ax2d& A)
{ pos.Mirror(A); }

//=======================================================================
//function : Mirrored
//purpose  : 
//=======================================================================

gp_Lin2d gp_Lin2d::Mirrored (const gp_Ax2d& A) const
{
  gp_Lin2d L = *this;
  L.pos.Mirror(A);
  return L;
}
 gp_Lin2d::gp_Lin2d ()
{ }

 gp_Lin2d::gp_Lin2d (const gp_Ax2d& A) : pos(A)
{ }

 gp_Lin2d::gp_Lin2d (const gp_Pnt2d& P,
			   const gp_Dir2d& V) : pos(P, V)
{ }

 void gp_Lin2d::Reverse()
{ pos.Reverse(); }

 gp_Lin2d gp_Lin2d::Reversed() const
{ 
  gp_Lin2d L = *this;
  L.pos.Reverse ();
  return L;
}

 void gp_Lin2d::SetDirection (const gp_Dir2d& V)
{ pos.SetDirection (V); }

 void gp_Lin2d::SetLocation (const gp_Pnt2d& P)
{ pos.SetLocation (P); }

 void gp_Lin2d::SetPosition (const gp_Ax2d& A)
{ pos = A; }

 void gp_Lin2d::Coefficients (double& A,
				    double& B,
				    double& C) const
{
  A =   pos.Direction().Y();
  B = - pos.Direction().X();
  C = -(A * pos.Location().X() + B * pos.Location().Y());
}

 const gp_Dir2d& gp_Lin2d::Direction() const
{ return pos.Direction(); }

 const gp_Pnt2d& gp_Lin2d::Location() const
{ return pos.Location(); }

    const gp_Ax2d& gp_Lin2d::Position() const
{ return pos; }

 double gp_Lin2d::Angle (const gp_Lin2d& Other) const
{ return pos.Direction().Angle (Other.pos.Direction()); }

 bool gp_Lin2d::Contains
(const gp_Pnt2d& P,
 const double LinearTolerance) const
{ return Distance(P) <= LinearTolerance; }

 double gp_Lin2d::Distance (const gp_Pnt2d& P) const
{
  gp_XY Coord = P.XY();
  Coord.Subtract ((pos.Location()).XY());
  double val = Coord.Crossed (pos.Direction().XY());
  if (val < 0) val = - val;
  return val;
}

 double gp_Lin2d::Distance (const gp_Lin2d& Other) const
{
  double D = 0.0;
  if (pos.IsParallel (Other.pos, gp::Resolution())) 
    D = Other.Distance(pos.Location());
  return D;
}

 double gp_Lin2d::SquareDistance (const gp_Pnt2d& P) const
{
  gp_XY Coord = P.XY();
  Coord.Subtract ((pos.Location()).XY());
  double D = Coord.Crossed (pos.Direction().XY());
  return D * D;
}

 double gp_Lin2d::SquareDistance (const gp_Lin2d& Other) const
{
  double D = 0.0;
  if (pos.IsParallel (Other.pos, gp::Resolution())) { 
    D = Other.Distance(pos.Location());
    D *= D;return D * D;
  }
  return D;
}

 gp_Lin2d gp_Lin2d::Normal (const gp_Pnt2d& P) const
{            
  return gp_Lin2d
    (gp_Ax2d
     (P,gp_Dir2d
      (-(pos.Direction().Y()), pos.Direction().X())));
}

 void gp_Lin2d::Rotate (const gp_Pnt2d& P, const double Ang)
{ pos.Rotate (P, Ang); }

 gp_Lin2d gp_Lin2d::Rotated (const gp_Pnt2d& P,
				   const double Ang) const
{
  gp_Lin2d L = *this;
  L.pos.Rotate (P, Ang);
  return L;
}

 void gp_Lin2d::Scale (const gp_Pnt2d& P, const double S)
{ pos.Scale(P, S);  }

 gp_Lin2d gp_Lin2d::Scaled (const gp_Pnt2d& P,
				  const double S) const
{
  gp_Lin2d L = *this;
  L.pos.Scale(P, S);
  return L;
}

 void gp_Lin2d::Transform (const gp_Trsf2d& T)
{ pos.Transform(T); }

 gp_Lin2d gp_Lin2d::Transformed (const gp_Trsf2d& T) const
{
  gp_Lin2d L = *this;
  L.pos.Transform(T);
  return L;
}

 void gp_Lin2d::Translate (const gp_Vec2d& V)
{ pos.Translate(V); }

 gp_Lin2d gp_Lin2d::Translated (const gp_Vec2d& V) const
{
  gp_Lin2d L = *this;
  L.pos.Translate(V); 
  return L;
}

 void gp_Lin2d::Translate (const gp_Pnt2d& P1,
				 const gp_Pnt2d& P2)
{ pos.Translate(P1, P2); }                 

 gp_Lin2d gp_Lin2d::Translated (const gp_Pnt2d& P1,
				      const gp_Pnt2d& P2) const
{
  gp_Lin2d L = *this;
  L.pos.Translate (gp_Vec2d(P1, P2));
  return L;
}

